#include <QDateTime> // for QDateTime
#include <QFileInfo> // for QFileInfo
#include <QLatin1Char> // for QLatin1Char
+#include <QMetaType> // for QMetaType, QMetaType::UInt
#include <QString> // for QString
#include <Qt> // for CaseInsensitive
#include <QtGlobal> // for qint64
}
}
+QString
+GarminFitFormat::fit_getstring(int size)
+{
+ if (fit_data.len < size) {
+ throw ReaderException("record truncated: expecting " + std::to_string(size) + " bytes, but only got " + std::to_string(fit_data.len) + ".");
+ }
+ QByteArray buf(size + 1, 0);
+ gbsize_t count = gbfread(buf.data(), size, 1, fin);
+ if (count != 1) {
+ throw ReaderException("unexpected end of file with fit_data.len=" + std::to_string(fit_data.len) + ".");
+ }
+ fit_data.len -= size;
+ return QString(buf);
+}
+
void
GarminFitFormat::fit_parse_definition_message(uint8_t header)
{
fit_data.message_def.insert(local_id, def);
}
-uint32_t
+QVariant
GarminFitFormat::fit_read_field(const fit_field_t& f)
{
/* https://forums.garmin.com/showthread.php?223645-Vivoactive-problems-plus-suggestions-for-future-firmwares&p=610929#post610929
}
return -1;
}
+ case 0x7:
+ return fit_getstring(f.size);
+
case 0x83: // sint16
case 0x84: // uint16
if (f.size == 2) {
//uint32_t starttime = 0; // ??? default ?
uint8_t event = 0xff;
uint8_t eventtype = 0xff;
+ QString name;
+ QString description;
if (global_opts.debug_level >= 7) {
debug_print(7,"%s: parsing fit data ID %d with num_fields=%d\n", MYNAME, def.global_id, def.fields.size());
debug_print(7,"%s: parsing field %d\n", MYNAME, i);
}
const fit_field_t& f = def.fields.at(i);
- uint32_t val = fit_read_field(f);
+ QVariant field = fit_read_field(f);
+ uint32_t val = -1;
+ if (field.canConvert(QMetaType::UInt)) {
+ val = field.toUInt();
+ }
if (f.id == kFieldTimestamp) {
if (global_opts.debug_level >= 7) {
debug_print(7,"%s: parsing fit data: timestamp=%d\n", MYNAME, val);
} // switch (f.id)
// end of case def.global_id = kIdEvent
break;
+
+ case kIdLocations:
+ switch (f.id) {
+ case kFieldLocLatitude:
+ if (global_opts.debug_level >= 7) {
+ debug_print(7,"%s: parsing fit data: lat=%d\n", MYNAME, val);
+ }
+ lat = val;
+ break;
+ case kFieldLocLongitude:
+ if (global_opts.debug_level >= 7) {
+ debug_print(7,"%s: parsing fit data: lon=%d\n", MYNAME, val);
+ }
+ lon = val;
+ break;
+ case kFieldLocAltitude:
+ if (global_opts.debug_level >= 7) {
+ debug_print(7,"%s: parsing fit data: alt=%d\n", MYNAME, val);
+ }
+ if (val != 0xffff) {
+ alt = val;
+ }
+ break;
+ case kFieldLocationName:
+ name = field.toString();
+ if (global_opts.debug_level >= 7) {
+ debug_print(7,"%s: parsing fit data: location name=%s\n", MYNAME, qPrintable(name));
+ }
+ break;
+ case kFieldLocationDescription:
+ description = field.toString();
+ if (global_opts.debug_level >= 7) {
+ debug_print(7,"%s: parsing fit data: location description=%s\n", MYNAME, qPrintable(description));
+ }
+ break;
+ default:
+ if (global_opts.debug_level >= 1) {
+ debug_print(1, "%s: unrecognized data type in GARMIN FIT locations: f.id=%d\n", MYNAME, f.id);
+ }
+ break;
+ } // switch (f.id)
+ // end of case def.global_id = kIdLocations
+ break;
default:
if (global_opts.debug_level >= 1) {
debug_print(1, "%s: unrecognized/unhandled global ID for GARMIN FIT: %d\n", MYNAME, def.global_id);
new_trkseg = true;
}
break;
+ case kIdLocations: { // locations message
+ if (lat == 0x7fffffff || lon == 0x7fffffff) {
+ break;
+ }
+ if (global_opts.debug_level >= 7) {
+ debug_print(7,"%s: storing fit data location %d\n", MYNAME, def.global_id);
+ }
+ auto* locpt = new Waypoint;
+ locpt->latitude = GPS_Math_Semi_To_Deg(lat);
+ locpt->longitude = GPS_Math_Semi_To_Deg(lon);
+ if (alt != 0xffff) {
+ locpt->altitude = (alt / 5.0) - 500;
+ }
+ locpt->shortname = name;
+ locpt->description = description;
+ waypt_add(locpt);
+ }
+ break;
}
}
#include <QHash> // for QHash
#include <QList> // for QList
#include <QString> // for QString
+#include <QVariant> // for QVariant
#include <QVector> // for QVector
#include "defs.h"
static constexpr int kIdLap = 19;
static constexpr int kIdRecord = 20;
static constexpr int kIdEvent = 21;
+ static constexpr int kIdLocations = 29;
static constexpr int kIdCourse = 31;
static constexpr int kIdCoursePoint = 32;
static constexpr int kFieldEventType = 1;
static constexpr int kEnumEventTypeStart = 0;
static constexpr int kFieldEventGroup = 4;
+// for global ID: locations
+ static constexpr int kFieldLocationName = 0;
+ static constexpr int kFieldLocLatitude = 1;
+ static constexpr int kFieldLocLongitude = 2;
+ static constexpr int kEnumLocationIcon = 3;
+ static constexpr int kFieldLocAltitude = 4;
+ static constexpr int kFieldLocationDescription = 6;
// for global ID: course
static constexpr int kFieldSport = 4;
static constexpr int kFieldName = 5;
uint8_t fit_getuint8();
uint16_t fit_getuint16();
uint32_t fit_getuint32();
+ QString fit_getstring(int size);
void fit_parse_definition_message(uint8_t header);
- uint32_t fit_read_field(const fit_field_t& f);
+ QVariant fit_read_field(const fit_field_t& f);
void fit_parse_data(const fit_message_def& def, int time_offset);
void fit_parse_data_message(uint8_t header);
void fit_parse_compressed_message(uint8_t header);